/*!
封装stat操作对象
*/
use crate::*;
use anyhow::Ok;
use stat::{Gfstat, Stat};
use std::path::PathBuf;

#[cfg(feature = "tracelog")]
use tracing::error;
#[cfg(feature = "rotatelog")]
use log::{debug, error, info, warn};
/**
gfs的结构信息句柄
 - master，当前Node的master地址（http://ip:port)，如果为空，则表示自己就是master
 - root 表示数据存储的根路径，其下也会存储tantivy索引，（bin/lib ?）
 */
pub struct Gfs {
    pub master: String,
    pub root: PathBuf,
    pub gstat: Gfstat,
}
impl Gfs {
    pub async fn new(master: String, root :&str) -> Self {

        let stat = Gfstat::new(root).await;
        return Gfs {
            gstat: stat,
            master,
            root: PathBuf::from(root)
        };
    }
    pub async fn get_last_id(&self) -> i32 {
        self.gstat.get_last_id().await
    }

    pub async fn get_next_from_id(&self, id:i32, limit:u32) -> anyhow::Result<Vec<Stat>> {
        self.gstat.get_next_from_id(id, limit).await
    }

    pub async fn get_last(&self, limit:u32) -> anyhow::Result<Vec<Stat>> {
        self.gstat.get_last(limit).await
    }
    pub async fn get_dir(&self,hash:&str, from:i32, limit:u32) -> anyhow::Result<Vec<Stat>> { 
        self.gstat.get_dir(hash, from, limit).await
    }
    pub async fn get_hash_files(&self,ihash:i32) -> anyhow::Result<Vec<Stat>> { 
        let hash = format!("{:02x}", ihash%256);
        self.gstat.get_hash_files(&hash).await
    }

    pub async fn add_stat(&self, hashcode: i32, idx: i32, fname: &str) -> anyhow::Result<i32> {
        if fname.len()== 0 {
            bail!("fname is null")
        }
        let mut rid = 0;
        if self.master.len() <= 0 {  // current is master
            let id = self
                .gstat
                .master_add(hashcode, fname)
                .await?;
            rid = id;
            if id != idx {
                // 这里的i32转换为16进制目录需要与写入部分严格一致：format!("{:02x}",hashcode)
                std::fs::rename( self.root.join(format!("{:02x}",hashcode)).join(format!("{:02x}",idx))
                      , self.root.join(format!("{:02x}",hashcode)).join(format!("{:02x}",id)))?;             
                error!("系统压力下可能出现的情况！ wish next id is {}, but return {}, so rename path to {}", idx, id, id);
            }
        } else {
            println!("slave only copy from master");
            let _id = self
            .gstat
            .slave_add(idx, fname, hashcode, 0)
            .await?;
        }
        Ok(rid)
    }

    pub async fn get_by_name(&self, hash:&str, fname:&str, id: i32, limit: u32) -> Result<Vec<Stat>> {
        let re = self.gstat.get_by_name(hash, fname, id, limit).await;
        re
    }

    pub async fn get_node_status(&self) -> Result<Vec<(String, i32)>> {
        let re = self.gstat.get_status().await;
        re
    }

}
